package com.fulihui.usercore.service;

import com.fulihui.usercore.api.UserAuthService;
import com.fulihui.usercore.biz.shard.UserTokenManager;
import com.fulihui.usercore.biz.shard.WechatUserManager;
import com.fulihui.usercore.common.util.AppProps;
import com.fulihui.usercore.core.processor.auth.AuthProcessorRegister;
import com.fulihui.usercore.dto.AuthDTO;
import com.fulihui.usercore.dto.WechatUserDTO;
import com.fulihui.usercore.enums.UserRegisterTypeEnum;
import com.fulihui.usercore.enums.WechatOpenIdTypeEnum;
import com.fulihui.usercore.request.auth.*;
import org.apache.dubbo.config.annotation.Service;
import org.near.servicesupport.error.CommonServiceErrorEnum;
import org.near.servicesupport.error.Errors;
import org.near.servicesupport.error.InvokeServiceException;
import org.near.servicesupport.result.ResultBuilder;
import org.near.servicesupport.result.TSingleResult;
import org.near.servicesupport.util.ServiceAssert;
import org.near.toolkit.common.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Date;

/**
 * @author Willard.Hu on 2016/11/7 0007.
 */
@Service(version = "1.0.0")
public class UserAuthServiceImpl implements UserAuthService {
    @Autowired
    private AuthProcessorRegister authProcessorRegister;
    @Autowired
    private UserTokenManager      userTokenManager;
    @Autowired
    private TransactionTemplate   transactionTemplate;
    @Autowired
    private WechatUserManager     wechatUserManager;
    @Autowired
    private AppProps appProps;
    @Override
    public TSingleResult<Boolean> registered(AuthQueryRequest request) {
        ServiceAssert.notBlank(request.getLoginId(),
                Errors.Commons.REQUEST_PARAMETER_ERROR);
        boolean b = authProcessorRegister.getProcessor(UserRegisterTypeEnum.MOBILE_QUICK.getCode())
                .registered(request.getLoginId());
        return ResultBuilder.succTSingle(b);
    }

    @Override
    public TSingleResult<AuthDTO> quickLogin(QuickAuthRequest request) {
        String userId = authProcessorRegister.getProcessor(
                UserRegisterTypeEnum.MOBILE_QUICK.getCode()).login(request);
        return ResultBuilder.succTSingle(authDTO(request.getLoginId(), userId));
    }

    @Override
    public TSingleResult<AuthDTO> accountLogin(AccountAuthRequest request) {
        String userId = authProcessorRegister.getProcessor(
                UserRegisterTypeEnum.ACCOUNT.getCode()).login(request);
        return ResultBuilder.succTSingle(authDTO(request.getLoginId(), userId));
    }
    @Override
    public TSingleResult<AuthDTO> accountRegister(AccountAuthRequest request) {
        String userId = authProcessorRegister.getProcessor(
                UserRegisterTypeEnum.ACCOUNT.getCode()).register(request);
        return ResultBuilder.succTSingle(authDTO(request.getLoginId(), userId));
    }

    @Override
    public TSingleResult<AuthDTO> accountRegisterAndBindingWechat(AccountAuthRequest request) {
        String userId = transactionTemplate.execute(status -> {
            String _userid= authProcessorRegister.getProcessor(
                    UserRegisterTypeEnum.ACCOUNT.getCode()).register(request);
            WechatUserDTO record = new WechatUserDTO();
            record.setOpenId(request.getOpenid());
            record.setOpenidType(StringUtil.isBlank(request.getOpenidType())? WechatOpenIdTypeEnum.WECHAT_MP.getCode():request.getOpenidType());
            String defaultAppid;
            if (WechatOpenIdTypeEnum.WECHAT_MP.getCode().equals(record.getOpenidType())) {
                defaultAppid = appProps.getWechatMpAppid();
            } else if (WechatOpenIdTypeEnum.NATIVE_APP.getCode().equals(
                    record.getOpenidType())) {
                defaultAppid = appProps.getWechatAppAppid();
            } else {
                throw new InvokeServiceException(CommonServiceErrorEnum.REQUEST_PARAMETER_ERROR);
            }
            record.setAppid(defaultAppid);
            record.setUnionid(request.getUnionid());
            record.setSubscribe(String.valueOf(request.getSubscribe()));
            if (request.getSubscribeTime() > 0) {
                record.setSubscribeTime(new Date(request.getSubscribeTime() * 1000L));
            }
            record.setUserId(_userid);
            wechatUserManager.bindingByUserId(record);
            return _userid;
        });
        return ResultBuilder.succTSingle(authDTO(request.getLoginId(), userId));
    }

    @Override
    public TSingleResult<AuthDTO> appAccountBindingWechatRegister(AccountAndBindingWechatAuthRequest request) {
        String userId = "";
        try {
            userId = authProcessorRegister.getProcessor(
                    UserRegisterTypeEnum.ACCOUNT_BINDING_WECHAT.getCode()).register(request);
        }catch (Exception e){
            return ResultBuilder.failTSingle(400,e.getMessage());
        }
        return ResultBuilder.succTSingle(authDTO(request.getLoginId(), userId));
    }

    private AccountAuthRequest buildAccountAuthRequest(AccountAuthRequest request){
        return null;
    }
    @Override
    public TSingleResult<AuthDTO> quickLoginAndBindingWechat(WechatAuthRequest request) {
        // 使用事务模版将事务往上提
        String userId = transactionTemplate.execute(status -> {
            String _userid;
            if (!authProcessorRegister.getProcessor(UserRegisterTypeEnum.MOBILE_QUICK.getCode())
                    .registered(request.getLoginId())) {
                _userid = authProcessorRegister.getProcessor(UserRegisterTypeEnum.WECHAT.getCode())
                        .login(request);
            } else {
                _userid = authProcessorRegister.getProcessor(
                        UserRegisterTypeEnum.MOBILE_QUICK.getCode()).login(request);
                WechatUserDTO record = new WechatUserDTO();
                record.setOpenId(request.getOpenid());
                record.setOpenidType(request.getOpenidType());
                record.setAppid(request.getAppid());
                record.setUnionid(request.getUnionid());
                record.setSubscribe(String.valueOf(request.getSubscribe()));
                if (request.getSubscribeTime() > 0) {
                    record.setSubscribeTime(new Date(request.getSubscribeTime() * 1000L));
                }
                record.setUserId(_userid);
                wechatUserManager.bindingByUserId(record);
            }
            return _userid;
        });
        // 未注册的直接微信注册
        return ResultBuilder.succTSingle(authDTO(request.getLoginId(), userId));
    }

    @Override
    public TSingleResult<AuthDTO> wechatLogin(WechatAuthRequest request) {
        String userId = authProcessorRegister.getProcessor(UserRegisterTypeEnum.WECHAT.getCode())
                .login(request);
        TSingleResult<AuthDTO> result;
        // 微信登入可以允许 Openid 查不到数据的情况
        if (StringUtil.isNotBlank(userId)) {
            result = ResultBuilder.succTSingle(authDTO(request.getLoginId(), userId));
        } else {
            result = ResultBuilder.succTSingle(null);
        }
        return result;
    }

    @Override
    public TSingleResult<AuthDTO> wechatRegister(WechatAuthRequest request) {
        String userId = authProcessorRegister.getProcessor(UserRegisterTypeEnum.WECHAT.getCode())
                .register(request);
        return ResultBuilder.succTSingle(authDTO(request.getLoginId(), userId));
    }

    @Override
    public TSingleResult<AuthDTO> weixinLogin(WechatAuthRequest request) {
        request.setLoginId(request.getUnionid());
        String userId = authProcessorRegister.getProcessor(
                UserRegisterTypeEnum.WEIXIN_AUTH.getCode()).login(request);
        return ResultBuilder.succTSingle(authDTO(request.getLoginId(), userId));
    }

    private AuthDTO authDTO(String loginId, String userId) {
        String token = userTokenManager.createToken(loginId, userId);
        AuthDTO authDTO = new AuthDTO();
        authDTO.setUserId(userId);
        authDTO.setToken(token);
        return authDTO;
    }
}
